﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ODataRegression.Framework.Core.TestOM;
using ODataRegression.Framework.Core.MetaDataOM;
using ODataRegression.Framework.Core.Shared;
using System.Xml;
using System.Text.RegularExpressions;
using ODataTestFrameworkCore.shared;

namespace ODataRegression.Framework.Core.Factories
{
    public abstract class ODataTestFactoryBase : IODataTestFactory
    {
        protected List<ODataTest> testList = new List<ODataTest>();
        protected ODataEntitySet entitySet;
        protected string ServiceName;
        protected string serviceRoot;
        // protected TestConfiguration testConfig;
        protected bool TraceOnly = true;
        protected ODataTestNames testName = ODataTestNames.None;
        protected string testTile = string.Empty;

        protected string EntityBaseURL = string.Empty;
        protected string QueryURLBase = string.Empty;
        protected string FinalQueryURL = string.Empty;
        protected int maxTestGenerationCount;
        protected int generatedTestCount;
        protected Regex verificationToken = new Regex("</feed>");
        protected Dictionary<string, string> firstresponse = null;

        public bool ISAvtiveTest
        {
            get
            {
                return TestConfigReader.RequestedODataTest.Keys.Contains(this.testName);
            }
        }
        public ODataTestFactoryBase(string serviceRoot, string ServiceName, ODataEntitySet entityset)
        {
            this.entitySet = entityset;
            this.ServiceName = ServiceName;
            this.serviceRoot = serviceRoot;
            //this.testConfig = testConfig;
        }

        public Dictionary<string, string> GetFirstResponse(string strURL)
        {
            string url = strURL;

            string testResult = HTTPHelpers.ExecuteGet(url + "&$top=1");
            string response = testResult;
            if (response != null)
            {
                if (response.Contains("<m:properties>"))
                {
                    int firstOutputIndex = response.IndexOf("<m:properties>");
                    int firstOutputLength = response.IndexOf("</m:properties>") - (firstOutputIndex - "</m:properties>".Length);
                    response = response.Substring(firstOutputIndex, firstOutputLength);
                    response = response.Replace("m:", string.Empty);
                    response = response.Replace("d:", string.Empty);
                    firstresponse = new Dictionary<string, string>();
                    string strValue = string.Empty;
                    XmlDocument xDoc = new XmlDocument();
                    xDoc.LoadXml(response);
                    foreach (XmlNode item in xDoc.DocumentElement.ChildNodes)
                    {
                        if (item.InnerText.Trim() != "")
                        {
                            if (item.Attributes.Count > 0)
                            {
                                if (item.Attributes["type"] != null)
                                {
                                    if (item.Attributes["type"].Value == "Edm.DateTime")
                                        firstresponse.Add(item.Name, "datetime'" + item.InnerText + "'");
                                    if (item.Attributes["type"].Value == "Edm.Int32")
                                        firstresponse.Add(item.Name, "%20" + item.InnerText + "%20");
                                    if (item.Attributes["type"].Value == "Edm.Int64")
                                        firstresponse.Add(item.Name, "%20" + item.InnerText + "%20");
                                }

                            }
                            else
                            {
                                firstresponse.Add(item.Name, "'" + item.InnerText + "'");
                            }
                        }
                    }
                    return firstresponse;
                }
                else
                {
                    return null;
                }

            }
            else
            {
                return null;
            }



        }
        public int GetMaxTestGenerationCount()
        {

            int maxTestGenerationCount = 9999;
            // Check out Multiplicity settings to generate max tests
            if (TestConfigReader.RequestedODataTest.ContainsKey(this.testName))
            {
                XmlAttributeCollection attrib = TestConfigReader.RequestedODataTest[this.testName];
                if (attrib["MaxTestGenerationCount"] != null &&
                    !string.IsNullOrEmpty(attrib["MaxTestGenerationCount"].Value)
                    && attrib["MaxTestGenerationCount"].Value != "*")
                {
                    maxTestGenerationCount = Convert.ToInt32(attrib["MaxTestGenerationCount"].Value);
                }
            }


            return maxTestGenerationCount;
        }
        public virtual List<ODataTest> CreateTestList()
        {
            //Console.Write(".");

            ODataTest test = new ODataTest(serviceRoot, this.ServiceName, (entitySet != null ? entitySet.CollectionName : "None"),
                (entitySet != null ? entitySet.Entity.Name : "None"), testName.ToString(), testTile, FinalQueryURL, UriResultType.Feed,
                verificationToken);

            testList.Add(test);
            GenerateClonedRepeatInstances(test);
            if (this.testName != ODataTestNames.EndPointTest && this.testName != ODataTestNames.Metadata)
            {
                AddReplacementIterations(test);
            }
            



            return testList;
        }

        private void GenerateClonedRepeatInstances(ODataTest item)
        {
            //List<ODataTest> tempList = new List<ODataTest>();
            // Generate Cloned Repeat Instances 
            if (TestConfigReader.RepeatCount > 0)
            {
               // foreach (ODataTest item in testList)
               // {
                    for (int i = 1; i <= TestConfigReader.RepeatCount; i++)
                    {
                        ODataTest temp = (ODataTest)item.Clone();
                        testList.Add(temp);
                    }
               // }

                //testList.AddRange(tempList);
                //tempList = null;
            }
        }
        private void AddReplacementIterations(ODataTest currentTest)
        {

            ODataTest temp = null;
            // if (this.testList != null && this.testList.Count > 0)
            // {
            if (TestConfigReader.IterationSettings != null)
            {

                foreach (XmlNode item in TestConfigReader.IterationSettings)
                {
                    foreach (XmlNode replacementPair in item.ChildNodes)
                    {
                        string updatedURL = StringHelpers.ExecuteStringFunctionViaReflection(replacementPair, currentTest.queryURL);

                        if (currentTest.queryURL != updatedURL)
                        {
                            temp = (ODataTest)currentTest.Clone();
                            temp.queryURL = updatedURL;

                            this.testList.Add(temp);
                            GenerateClonedRepeatInstances(temp);
                        }






                    }
                }

            }
            //}
        }


    }
}
